package com.unlcn.ils.wms.backend.service.outbound.impl;

import cn.huiyunche.commons.domain.PageVo;
import cn.huiyunche.commons.domain.ResultDTOWithPagination;
import cn.huiyunche.commons.exception.BusinessException;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.unlcn.ils.wms.backend.bo.baseDataBO.WmsWarehouseBO;
import com.unlcn.ils.wms.backend.bo.outboundBO.WmsPreparationPlanBO;
import com.unlcn.ils.wms.backend.bo.outboundBO.WmsPreparationVehicleDetailBO;
import com.unlcn.ils.wms.backend.enums.*;
import com.unlcn.ils.wms.backend.service.baseData.WmsWarehouseService;
import com.unlcn.ils.wms.backend.service.outbound.WmsPreparationPlanService;
import com.unlcn.ils.wms.backend.service.outbound.WmsShipmentPlanService;
import com.unlcn.ils.wms.backend.util.DateUtils;
import com.unlcn.ils.wms.base.businessDTO.inbound.AsnOrderDTO;
import com.unlcn.ils.wms.base.dto.WmsPreparationPlanDTO;
import com.unlcn.ils.wms.base.dto.WmsPreparationPlanResultDTO;
import com.unlcn.ils.wms.base.dto.WmsPreparationVehicleDetailDTO;
import com.unlcn.ils.wms.base.mapper.additional.WmsInboundAsnOrderAddMapper;
import com.unlcn.ils.wms.base.mapper.additional.wmsOutbound.WmsOutboundTaskExtMapper;
import com.unlcn.ils.wms.base.mapper.additional.wmsOutbound.WmsPreparationPlanExtMapper;
import com.unlcn.ils.wms.base.mapper.extmapper.WmsDepartureRegisterExtMapper;
import com.unlcn.ils.wms.base.mapper.extmapper.WmsInboundOrderDetailExtMapper;
import com.unlcn.ils.wms.base.mapper.extmapper.WmsShipmentPlanExtMapper;
import com.unlcn.ils.wms.base.mapper.inbound.WmsInboundOrderDetailMapper;
import com.unlcn.ils.wms.base.mapper.inbound.WmsInboundOrderMapper;
import com.unlcn.ils.wms.base.mapper.outbound.WmsEstimateLaneMapper;
import com.unlcn.ils.wms.base.mapper.outbound.WmsOutboundTaskMapper;
import com.unlcn.ils.wms.base.mapper.outbound.WmsPreparationPlanMapper;
import com.unlcn.ils.wms.base.mapper.outbound.WmsPreparationVehicleDetailMapper;
import com.unlcn.ils.wms.base.mapper.stock.WmsInventoryLocationMapper;
import com.unlcn.ils.wms.base.mapper.stock.WmsShipmentPlanMapper;
import com.unlcn.ils.wms.base.mapper.sys.SysUserMapper;
import com.unlcn.ils.wms.base.model.inbound.WmsInboundOrder;
import com.unlcn.ils.wms.base.model.inbound.WmsInboundOrderDetail;
import com.unlcn.ils.wms.base.model.inbound.WmsInboundOrderDetailExample;
import com.unlcn.ils.wms.base.model.inbound.WmsInboundOrderExample;
import com.unlcn.ils.wms.base.model.outbound.*;
import com.unlcn.ils.wms.base.model.stock.*;
import com.unlcn.ils.wms.base.model.sys.SysUser;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by DELL on 2017/9/26.
 */
@Service
public class WmsPreparationPlanServiceImpl implements WmsPreparationPlanService {
    private Logger LOGGER = LoggerFactory.getLogger(WmsPreparationPlanServiceImpl.class);

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Autowired
    private WmsPreparationPlanExtMapper wmsPreparationPlanExtMapper;

    @Autowired
    private WmsPreparationPlanMapper wmsPreparationPlanMapper;

    @Autowired
    private WmsPreparationVehicleDetailMapper wmsPreparationVehicleDetailMapper;

    @Autowired
    private WmsOutboundTaskMapper wmsOutboundTaskMapper;

    @Autowired
    private WmsInboundAsnOrderAddMapper wmsInboundAsnOrderAddMapper;

    @Autowired
    private WmsEstimateLaneMapper wmsEstimateLaneMapper;

    @Autowired
    private WmsInventoryLocationMapper wmsInventoryLocationMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private WmsShipmentPlanService wmsShipmentPlanService;

    @Autowired
    private WmsInboundOrderDetailMapper inboundOrderDetailMapper;

    @Autowired
    private WmsShipmentPlanMapper wmsShipmentPlanMapper;//发运计划

    @Autowired
    private WmsShipmentPlanExtMapper wmsShipmentPlanExtMapper;

    @Autowired
    private WmsWarehouseService wmsWarehouseService;

    @Autowired
    private WmsInboundOrderMapper wmsInboundOrderMapper;

    @Autowired
    private WmsOutboundTaskExtMapper wmsOutboundTaskExtMapper;

    @Autowired
    private WmsDepartureRegisterExtMapper wmsDepartureRegisterExtMapper;

    @Override
    public Map<String, Object> list(Map<String, Object> paramMap) {
        Map<String, Object> resultMap = Maps.newHashMap();
        Integer pageNo = Integer.valueOf(paramMap.get("pageNo").toString());
        Integer pageSize = Integer.valueOf(paramMap.get("pageSize").toString());
        paramMap.put("limitStart", (pageNo - 1) * pageSize < 0 ? 0 : (pageNo - 1) * pageSize);
        paramMap.put("limitEnd", pageSize);
        paramMap.put("orderBy", "gmt_create desc");
        //List<WmsPreparationPlan> infos = wmsPreparationPlanExtMapper.queryForList(paramMap);
        List<WmsPreparationPlan> infos = wmsPreparationPlanExtMapper.queryForListNew(paramMap);
        List<WmsPreparationPlanBO> wmsPreparationPlanBOList = Lists.newArrayList();
        //查询当前登陆人
        SysUser sysUser = sysUserMapper.selectByPrimaryKey(Integer.valueOf(paramMap.get("opStaff").toString()));
        if (Objects.isNull(sysUser)) {
            throw new BusinessException("未查询到当前登录人");
        }
        if (CollectionUtils.isNotEmpty(infos)) {
            infos.forEach((WmsPreparationPlan v) -> {
                WmsPreparationPlanBO bo = new WmsPreparationPlanBO();
                BeanUtils.copyProperties(v, bo);
                bo.setPpOperationStaff(StringUtils.isNotBlank(v.getPpOperationStaff()) ? v.getPpOperationStaff() : sysUser.getName());
                bo.setGmtCreate(v.getGmtCreate() != null ? sdf.format(v.getGmtCreate()) : "");
                bo.setPpEstimateLoadingTime(v.getPpEstimateLoadingTime() != null ? sdf.format(v.getPpEstimateLoadingTime()) : "");
                bo.setPpEstimateFinishTime(v.getPpEstimateFinishTime() != null ? sdf.format(v.getPpEstimateFinishTime()) : "");
                //重庆库  备料计划列表页面增加显示板车实际入场时间/出场时间
                updateSetGateInOutTime(paramMap, v, bo);
                wmsPreparationPlanBOList.add(bo);
            });
            resultMap.put("wmsPreparationPlanBO", wmsPreparationPlanBOList);
        }
        resultMap.put("wmsPreparationPlanQuery", paramMap);
        paramMap.put("totalRecord", wmsPreparationPlanExtMapper.queryForCountNew(paramMap));
        return resultMap;
    }

    /**
     * 备料计划管理 - 获取备料详情
     * <p>
     * 2018-5-7 君马库新需求: 备料计划管理菜单,备料单明细新增车辆物料编码,新增库位展示
     * </p>
     */
    @Override
    public ArrayList<WmsPreparationVehicleDetailBO> getVehicleDetail(String ppId) {
        //linbao 2017-11-17
        WmsPreparationPlan plan = wmsPreparationPlanMapper.selectByPrimaryKey(Long.parseLong(ppId));
        if (plan == null) {
            throw new BusinessException("找不到对应的备料计划");
        }
        ArrayList<WmsPreparationVehicleDetailBO> result = Lists.newArrayList();
        //2018-5-7 君马库新需求: 重庆库逻辑
        if (WhCodeEnum.UNLCN_XN_CQ.getValue().equals(plan.getPpWhCode())) {
            byte del = DeleteFlagEnum.DELETED.getValue();
            List<WmsPreparationVehicleDetail> detailList = wmsPreparationPlanExtMapper.getVehicleDetail(Long.valueOf(ppId), del);
            if (CollectionUtils.isNotEmpty(detailList)) {
                detailList.forEach((WmsPreparationVehicleDetail v) -> {
                    WmsPreparationVehicleDetailBO detailBO = new WmsPreparationVehicleDetailBO();
                    BeanUtils.copyProperties(v, detailBO);
                    //已出库查询备料司机
                    WmsOutboundTaskExample taskExample = new WmsOutboundTaskExample();
                    WmsOutboundTaskExample.Criteria criteria = taskExample.createCriteria();
                    criteria.andOtVinEqualTo(v.getVdVin());
                    criteria.andIsDeletedNotEqualTo(DeleteFlagEnum.DELETED.getValue());
                    //过滤已取消的任务 - 2017-11-04
                    criteria.andOtStatusNotEqualTo(String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_CANCLE.getValue()));
                    //查询司机
                    List<WmsOutboundTask> wmsOutboundTasks = wmsOutboundTaskMapper.selectByExample(taskExample);
                    saveDriverDetail(detailBO, wmsOutboundTasks);
                    String dispNo = plan.getPpGroupDispNo();
                    //判断是否需要剔除 null-不管, 0-需要剔除, 1-有任务需要置灰
                    if (StringUtils.isNotBlank(dispNo) && StringUtils.isNotBlank(v.getVdVin())) {
                        String statusForTask = wmsOutboundTaskExtMapper.getStatusForDeleteShipment(dispNo, v.getVdVin());
                        if (StringUtils.isBlank(statusForTask)) {
                            Integer count = wmsOutboundTaskExtMapper.countShipStatusForDeleteShipment(dispNo, v.getVdVin());
                            if (count != null && count > 0) {
                                detailBO.setDeleteFlag(0);
                            }
                        } else {
                            if (String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_NEW.getValue()).equals(statusForTask)
                                    || String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_READY.getValue()).equals(statusForTask)) {
                                detailBO.setDeleteFlag(0);
                            } else if (String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_GOING.getValue()).equals(statusForTask)
                                    || String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_FINISHED.getValue()).equals(statusForTask)) {
                                detailBO.setDeleteFlag(1);
                            }
                        }
                    }
                    result.add(detailBO);
                });
            }
            //2018-5-7 君马库新需求: 君马库逻辑
        } else if (WhCodeEnum.JM_XY.getValue().equals(plan.getPpWhCode()) ||
                WhCodeEnum.JM_CS.getValue().equals(plan.getPpWhCode())) {
            HashMap<String, Object> params = Maps.newHashMap();
            params.put("notDel", DeleteFlagEnum.NORMAL.getValue());
            params.put("ppId", ppId);
            List<WmsPreparationVehicleDetailDTO> detailList = wmsPreparationPlanExtMapper.selectDetailListByParamForJM(params);
            //List<WmsPreparationVehicleDetail> detailList = wmsPreparationPlanExtMapper.getVehicleDetail(Long.valueOf(ppId), del);
            if (CollectionUtils.isNotEmpty(detailList)) {
                detailList.forEach((WmsPreparationVehicleDetailDTO v) -> {
                    WmsPreparationVehicleDetailBO detailBO = new WmsPreparationVehicleDetailBO();
                    BeanUtils.copyProperties(v, detailBO);
                    //已出库查询备料司机
                    WmsOutboundTaskExample taskExample = new WmsOutboundTaskExample();
                    WmsOutboundTaskExample.Criteria criteria = taskExample.createCriteria();
                    criteria.andOtVinEqualTo(v.getVdVin());
                    criteria.andIsDeletedNotEqualTo(DeleteFlagEnum.DELETED.getValue());
                    //过滤已取消的任务 - 2017-11-04
                    criteria.andOtStatusNotEqualTo(String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_CANCLE.getValue()));
                    //查询司机
                    List<WmsOutboundTask> wmsOutboundTasks = wmsOutboundTaskMapper.selectByExample(taskExample);
                    saveDriverDetail(detailBO, wmsOutboundTasks);
                    result.add(detailBO);
                });
            }

        }
        return result;
    }

    /**
     * 保存移库司机信息
     *
     * @param detailBO         参数封装
     * @param wmsOutboundTasks 任务列表
     */
    private void saveDriverDetail(WmsPreparationVehicleDetailBO detailBO, List<WmsOutboundTask> wmsOutboundTasks) {
        if (CollectionUtils.isNotEmpty(wmsOutboundTasks)) {
            WmsOutboundTask outboundTask = wmsOutboundTasks.get(0);
            String otDriver = outboundTask.getOtDriver();//备料司机的id
            if (StringUtils.isNotBlank(otDriver) && StringUtils.isNumeric(otDriver)) {
                SysUser sysUser = sysUserMapper.selectByPrimaryKey(Integer.parseInt(otDriver));
                if (!Objects.equals(sysUser, null)) {
                    detailBO.setDriverId(otDriver);
                    detailBO.setDriverName(sysUser.getName());
                }
            } else {
                detailBO.setDriverName(otDriver);
            }
        }
    }

    /**
     * 生成备料任务
     *
     * @param estimateLaneId           装车道
     * @param wmsPreparationPlanBOList 备料计划列表参数
     * @param whCode                   仓库code
     */
    @Override
    public void savePreparationTask(Long estimateLaneId, List<WmsPreparationPlanBO> wmsPreparationPlanBOList, String whCode) throws Exception {
        WmsEstimateLaneExample wmsEstimateLaneExample = new WmsEstimateLaneExample();
        wmsEstimateLaneExample.createCriteria().andElIdEqualTo(estimateLaneId);
        List<WmsEstimateLane> wmsEstimateLane = wmsEstimateLaneMapper.selectByExample(wmsEstimateLaneExample);
        if (CollectionUtils.isEmpty(wmsPreparationPlanBOList)) {
            throw new BusinessException("请选择要生成备料任务的数据!");
        }
        if (CollectionUtils.isEmpty(wmsEstimateLane)) {
            throw new BusinessException("未查询到对应的装车道信息!");
        }
        WmsEstimateLane estimateLane = wmsEstimateLane.get(0);
        //校验plan status=10 才能生成任务
        WmsPreparationPlan wmsPreparationPlan = checkPreparationPlan(wmsPreparationPlanBOList);
        for (WmsPreparationPlanBO wmsPreparationPlanBO : wmsPreparationPlanBOList) {
            byte del = DeleteFlagEnum.DELETED.getValue();
            List<WmsPreparationVehicleDetail> wmsPreparationVehicleDetailList = wmsPreparationPlanExtMapper.getVehicleDetail(wmsPreparationPlanBO.getPpId(), del);
            wmsPreparationPlan.setPpStatus(String.valueOf(WmsPreparationPlanEnum.WMS_PLAN_START.getValue()));
            wmsPreparationPlan.setPpWhCode(estimateLane.getElWhCode());
            wmsPreparationPlan.setPpWhName(estimateLane.getElWhName());
            wmsPreparationPlan.setGmtUpdate(new Date());
            wmsPreparationPlan.setPpEstimateLane(wmsEstimateLane.get(0).getElName());
            wmsPreparationPlanMapper.updateByPrimaryKeySelective(wmsPreparationPlan);

            //wmsPreparationVehicleDetailList.stream().forEach(wmsPreparationVehicleDetail -> {
            //    wmsOutboundTaskMapper.insert(getWmsOutboundTask(wmsPreparationPlanBO, wmsPreparationVehicleDetail, estimateLane, whCode));
            //});
            WmsPreparationPlan primaryKeyPlan = null;
            if (wmsPreparationPlanBO.getPpId() != null) {
                primaryKeyPlan = wmsPreparationPlanMapper.selectByPrimaryKey(wmsPreparationPlanBO.getPpId());
            }
            for (WmsPreparationVehicleDetail wmsPreparationVehicleDetail : wmsPreparationVehicleDetailList) {
                WmsOutboundTask wmsOutboundTask = getWmsOutboundTask(wmsPreparationPlanBO, wmsPreparationVehicleDetail, estimateLane, whCode);
                if (primaryKeyPlan != null) {
                    if (WmsShipmentPlanDlvTypeEnum.A1.getValue().equals(primaryKeyPlan.getPpDlvType())) {
                        wmsOutboundTask.setOtType(OutBoundTaskTypeEnum.NORMAL_OUT.getCode());
                    } else if (WmsShipmentPlanDlvTypeEnum.A2.getValue().equals(primaryKeyPlan.getPpDlvType())) {
                        wmsOutboundTask.setOtType(OutBoundTaskTypeEnum.DIS_OUT.getCode());
                    }
                }
                //借用出库
                if (StringUtils.isNotBlank(wmsOutboundTask.getHoHandoverNumber())
                        && wmsOutboundTask.getHoHandoverNumber().startsWith(OrderHeadEnum.BORROW.getCode())) {
                    wmsOutboundTask.setOtType(OutBoundTaskTypeEnum.BORROW_OUT.getCode());
                }
                wmsOutboundTask.setOtIsChange(TaskIsNeedChangeEnum.NO_CHANGE.getCode());//设置未换车
                wmsOutboundTaskMapper.insertSelective(wmsOutboundTask);
            }
        }
    }

    private WmsPreparationPlan checkPreparationPlan(List<WmsPreparationPlanBO> wmsPreparationPlanBOList) {
        //查询计划 校验是否重复
        WmsPreparationPlan wmsPreparationPlan;
        Long ppId = wmsPreparationPlanBOList.get(0).getPpId();
        WmsPreparationPlanExample wmsPreparationPlanExample = new WmsPreparationPlanExample();
        WmsPreparationPlanExample.Criteria criteria = wmsPreparationPlanExample.createCriteria();
        criteria.andPpIdEqualTo(ppId);
        criteria.andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue());
        List<WmsPreparationPlan> wmsPreparationPlans = wmsPreparationPlanMapper.selectByExample(wmsPreparationPlanExample);
        if (CollectionUtils.isEmpty(wmsPreparationPlans)) {
            throw new BusinessException("未查询到对应备料单:" + ppId + "的计划信息");
        } else {
            wmsPreparationPlan = wmsPreparationPlans.get(0);
            if (!String.valueOf(WmsPreparationPlanEnum.WMS_PLAN_NEW.getValue()).equals(wmsPreparationPlan.getPpStatus())) {
                throw new BusinessException("该计划:" + ppId + "已创建任务,请勿重复操作!");
            }
        }
        return wmsPreparationPlan;
    }

    /**
     * 创建备料任务 - 西南新
     * linbao 2017-11-21 需要找寻老的任务进行判断
     * <p>
     * 2018-1-25 新增重庆库增加校验 只能一单未开始的时候创建备料计划
     * </p>
     *
     * @param estimateLaneId           装车道
     * @param wmsPreparationPlanBOList 备料参数封装
     */
    @Override
    public void savePreparationTaskForCqNew(Long estimateLaneId, List<WmsPreparationPlanBO> wmsPreparationPlanBOList, String whCode) throws Exception {
        WmsEstimateLaneExample wmsEstimateLaneExample = new WmsEstimateLaneExample();
        wmsEstimateLaneExample.createCriteria().andElIdEqualTo(estimateLaneId);
        List<WmsEstimateLane> wmsEstimateLane = wmsEstimateLaneMapper.selectByExample(wmsEstimateLaneExample);
        if (CollectionUtils.isEmpty(wmsPreparationPlanBOList)) {
            throw new BusinessException("请选择要生成备料任务的数据!");
        }
        if (CollectionUtils.isEmpty(wmsEstimateLane)) {
            throw new BusinessException("未查询到对应的装车道信息!");
        }
        if (wmsPreparationPlanBOList.size() > 1)
            throw new BusinessException("此仓库不支持批量创建备料计划");
        //2018-1-25 重庆库增加校验,一时间内只有一条备料计划是已备料或者进行中的数据(防止手机领取任务的时候报错)
        HashMap<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("whCode", WhCodeEnum.UNLCN_XN_CQ.getValue());
        paramMap.put("notDel", DeleteFlagEnum.NORMAL.getValue());
        paramMap.put("status_20", WmsPreparationPlanEnum.WMS_PLAN_START.getValue());
        paramMap.put("status_30", WmsPreparationPlanEnum.WMS_PLAN_CONFIRM.getValue());
        List<WmsPreparationPlan> list = wmsPreparationPlanExtMapper.selectPreparaingPlanByParams(paramMap);
        if (CollectionUtils.isNotEmpty(list))
            throw new BusinessException("系统仍存在进行中的备料单,单号:" + list.get(0).getPpId() + "请先完成");
        WmsEstimateLane estimateLane = wmsEstimateLane.get(0);
        //校验plan status=10 才能生成任务
        WmsPreparationPlan wmsPreparationPlan = checkPreparationPlan(wmsPreparationPlanBOList);
        for (WmsPreparationPlanBO wmsPreparationPlanBO : wmsPreparationPlanBOList) {
            byte del = DeleteFlagEnum.DELETED.getValue();
            List<WmsPreparationVehicleDetail> wmsPreparationVehicleDetailList = wmsPreparationPlanExtMapper.getVehicleDetail(wmsPreparationPlanBO.getPpId(), del);
            wmsPreparationPlan.setPpStatus(String.valueOf(WmsPreparationPlanEnum.WMS_PLAN_START.getValue()));
            wmsPreparationPlan.setPpWhCode(estimateLane.getElWhCode());
            wmsPreparationPlan.setPpWhName(estimateLane.getElWhName());
            wmsPreparationPlan.setGmtUpdate(new Date());
            wmsPreparationPlan.setPpEstimateLane(wmsEstimateLane.get(0).getElName());
            wmsPreparationPlanMapper.updateByPrimaryKeySelective(wmsPreparationPlan);
            WmsPreparationPlan primaryKeyPlan = null;
            if (wmsPreparationPlanBO.getPpId() != null) {
                primaryKeyPlan = wmsPreparationPlanMapper.selectByPrimaryKey(wmsPreparationPlanBO.getPpId());
            }
            for (WmsPreparationVehicleDetail wmsPreparationVehicleDetail : wmsPreparationVehicleDetailList) {
                WmsOutboundTask oldOutboundTask = getOldOutboundTask(wmsPreparationVehicleDetail.getVdVin(), whCode);
                if (oldOutboundTask != null) {
                    oldOutboundTask.setOtPreparationMaterialNo(wmsPreparationPlanBO.getPpPreparationMaterialNo());//备料单号
                    oldOutboundTask.setOtBlId(String.valueOf(wmsPreparationPlanBO.getPpId()));//备料id
                    oldOutboundTask.setOtEstimateLane(estimateLane.getElName());//装车道
                    oldOutboundTask.setGmtModify(new Date());
                    oldOutboundTask.setIsDeleted(DeleteFlagEnum.NORMAL.getValue());
                    wmsOutboundTaskMapper.updateByPrimaryKeySelective(oldOutboundTask);
                } else {

                    WmsOutboundTask wmsOutboundTask = getWmsOutboundTask(wmsPreparationPlanBO, wmsPreparationVehicleDetail, estimateLane, whCode);
                    if (primaryKeyPlan != null) {
                        if (WmsShipmentPlanDlvTypeEnum.A1.getValue().equals(primaryKeyPlan.getPpDlvType())) {
                            wmsOutboundTask.setOtType(OutBoundTaskTypeEnum.NORMAL_OUT.getCode());
                        } else if (WmsShipmentPlanDlvTypeEnum.A2.getValue().equals(primaryKeyPlan.getPpDlvType())) {
                            wmsOutboundTask.setOtType(OutBoundTaskTypeEnum.DIS_OUT.getCode());
                        }
                    }
                    //借用出库
                    if (StringUtils.isNotBlank(wmsOutboundTask.getHoHandoverNumber())
                            && wmsOutboundTask.getHoHandoverNumber().startsWith(OrderHeadEnum.BORROW.getCode())) {
                        wmsOutboundTask.setOtType(OutBoundTaskTypeEnum.BORROW_OUT.getCode());
                    }
                    wmsOutboundTask.setOtIsChange(TaskIsNeedChangeEnum.NO_CHANGE.getCode());//设置未换车
                    wmsOutboundTaskMapper.insert(wmsOutboundTask);
                }
            }
        }
    }

    /**
     * 查询老任务 - 西南
     * <p>
     * 2018-2-6 bugfix 修复任务删除之后再创建备料计划错误
     * </p>
     */
    private WmsOutboundTask getOldOutboundTask(String vin, String whCode) {
        if (StringUtils.isNotBlank(vin) && StringUtils.isNotBlank(whCode)) {
            WmsOutboundTaskExample taskExample = new WmsOutboundTaskExample();
            taskExample.setOrderByClause(" gmt_create desc, ot_id desc");
            taskExample.setLimitStart(0);
            taskExample.setLimitEnd(1);
            taskExample.createCriteria()
                    .andOtWhCodeEqualTo(whCode)
                    .andOtVinEqualTo(vin);
            List<WmsOutboundTask> taskList = wmsOutboundTaskMapper.selectByExample(taskExample);
            if (CollectionUtils.isNotEmpty(taskList) && taskList.get(0) != null) {
                WmsOutboundTask outboundTask = taskList.get(0);
                if (outboundTask.getOtQuitFlag() != null
                        && String.valueOf(TaskQuitFlagEnum.HAS_QUIT.getValue()).equals(String.valueOf(outboundTask.getOtQuitFlag()))) {
                    return null;
                } else {
                    //if (String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_CANCLE.getValue()).equals(outboundTask.getOtStatus())) {
                    //    return null;
                    //} else if (String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_FINISHED.getValue()).equals(outboundTask.getOtStatus())) {
                    //    return outboundTask;
                    //} else {
                    //    throw new BusinessException("该车架号" + vin + "存在未完成的任务, 请核实");
                    //}
                    //bugfix 修复任务删除之后再创建备料计划错误
                    if (String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_CANCLE.getValue()).equals(outboundTask.getOtStatus())) {
                        return null;
                    } else {
                        return outboundTask;
                    }
                }
            }
        }
        return null;
    }


    /**
     * 根据交接单号获取备料详情
     */
    @Override
    public List<WmsPreparationVehicleDetail> getDetailListByHandoverNo(String handoverNo) {
        LOGGER.info("WmsPreparationPlanServiceImpl.getDetailListByHandoverNo handoverNo: {}", handoverNo);
        if (StringUtils.isNotBlank(handoverNo)) {
            WmsPreparationVehicleDetailExample example = new WmsPreparationVehicleDetailExample();
            example.createCriteria().andHoHandoverNumberEqualTo(handoverNo);
            return wmsPreparationVehicleDetailMapper.selectByExample(example);
        }
        return null;
    }

    /**
     * 根据组版单号获取备料计划
     */
    @Override
    public WmsPreparationPlan getPreparationPlanByGroupDispNo(String groupDispNo) {
        LOGGER.info("WmsPreparationPlanServiceImpl.getPreparationPlanByGroupDispNo groupDispNo: {}", groupDispNo);
        if (StringUtils.isNotBlank(groupDispNo)) {
            WmsPreparationPlanExample example = new WmsPreparationPlanExample();
            example.createCriteria().andPpGroupDispNoEqualTo(groupDispNo);

            List<WmsPreparationPlan> preparationPlanList = wmsPreparationPlanMapper.selectByExample(example);
            if (CollectionUtils.isNotEmpty(preparationPlanList)) {
                return preparationPlanList.get(0);
            }
        }
        return null;
    }

    /**
     * 获取出库作业任务
     */
    private WmsOutboundTask getWmsOutboundTask(WmsPreparationPlanBO wmsPreparationPlanBO,
                                               WmsPreparationVehicleDetail wmsPreparationVehicleDetail,
                                               WmsEstimateLane wmsEstimateLane, String whCode) throws Exception {

        //校验该车辆在库存表中是否存在
        WmsInventoryLocationExample inventoryLocationExample = new WmsInventoryLocationExample();
        WmsInventoryLocationExample.Criteria criteria = inventoryLocationExample.createCriteria();
        criteria.andInvlocVinEqualTo(wmsPreparationVehicleDetail.getVdVin());
        if (!WarehouseEnum.JM_CS.getWhCode().equals(whCode) && !WarehouseEnum.JM_XY.getWhCode().equals(whCode)) {
            criteria.andIsDeletedNotEqualTo(DeleteFlagEnum.DELETED.getValue());
        }
        List<WmsInventoryLocation> wmsInventoryLocations = wmsInventoryLocationMapper.selectByExample(inventoryLocationExample);
        if (CollectionUtils.isEmpty(wmsInventoryLocations)) {
            throw new BusinessException("该车辆" + wmsPreparationVehicleDetail.getVdVin() + "还未进行入库作业,请先入库");
        }
        WmsOutboundTask wmsOutboundTask = new WmsOutboundTask();
        //wmsOutboundTask.setOtTaskNo();//备料任务号
        wmsOutboundTask.setOtPreparationMaterialNo(wmsPreparationPlanBO.getPpPreparationMaterialNo());//备料单号
        wmsOutboundTask.setOtVin(wmsPreparationVehicleDetail.getVdVin());//车架号(vin码)
        wmsOutboundTask.setOtVehicleSpecName(wmsPreparationVehicleDetail.getVdVehicleName());//车型

        //设置库存库存信息
        AsnOrderDTO asnOrderDTO = wmsInboundAsnOrderAddMapper.queryByVin(wmsPreparationVehicleDetail.getVdVin());
        if (null != asnOrderDTO && !Objects.isNull(asnOrderDTO) && CollectionUtils.isNotEmpty(asnOrderDTO.getAsnOrderDetailDTOList())) {
            wmsOutboundTask.setOtZoneCode(asnOrderDTO.getAsnOrderDetailDTOList().get(0).getOddWhZoneCode());
            wmsOutboundTask.setOtZoneName(asnOrderDTO.getAsnOrderDetailDTOList().get(0).getOddWhZoneName());
            wmsOutboundTask.setOtLocationCode(asnOrderDTO.getAsnOrderDetailDTOList().get(0).getOddWhLocCode());
            wmsOutboundTask.setOtLcoationName(asnOrderDTO.getAsnOrderDetailDTOList().get(0).getOddWhLocName());
        } else {
            WmsInventoryLocationExample locationExample = new WmsInventoryLocationExample();
            locationExample.setOrderByClause(" invloc_id desc");
            locationExample.createCriteria().andInvlocVinEqualTo(wmsPreparationVehicleDetail.getVdVin());
            List<WmsInventoryLocation> locationList = wmsInventoryLocationMapper.selectByExample(locationExample);
            if (CollectionUtils.isNotEmpty(locationList)) {
                wmsOutboundTask.setOtZoneCode(locationList.get(0).getInvlocZoneCode());
                wmsOutboundTask.setOtZoneName(locationList.get(0).getInvlocZoneName());
                wmsOutboundTask.setOtLocationCode(locationList.get(0).getInvlocLocCode());
                wmsOutboundTask.setOtLcoationName(locationList.get(0).getInvlocLocName());
            }
        }

        wmsOutboundTask.setOtWaybillNo(wmsPreparationVehicleDetail.getVdWaybillNo());
        wmsOutboundTask.setOtEstimateLane(wmsEstimateLane.getElName());//装车道
        wmsOutboundTask.setOtStatus(String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_NEW.getValue()));//状态
        wmsOutboundTask.setInspectStatus(WmsOutboundInspectStatusEnum.WAYBILL_INIT.getValue());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        wmsOutboundTask.setOtTaskNo("TA" + sdf.format(new Date()));//设置备料任务号

        // 在生成任务的时候不会保存备料司机, 在司机领取任务的时候才会保存进去
        //wmsOutboundTask.setOtDriver(wmsPreparationPlanBO.getPpOperationStaff());//备料司机
        wmsOutboundTask.setOtBlId(String.valueOf(wmsPreparationPlanBO.getPpId()));//备料id
        wmsOutboundTask.setOtWhName(wmsEstimateLane.getElWhName());
        wmsOutboundTask.setOtWhCode(wmsEstimateLane.getElWhCode());//仓库code
        wmsOutboundTask.setIsDeleted((byte) 1);//逻辑未删除
        //交接单号
        wmsOutboundTask.setHoHandoverNumber(wmsPreparationVehicleDetail.getHoHandoverNumber());

        //获取发运计划 - 设置货主, 目的地, 出库类型
        if (WarehouseEnum.JM_CS.getWhCode().equals(whCode) || WarehouseEnum.JM_XY.getWhCode().equals(whCode)) {
            //君马库
            if (wmsPreparationVehicleDetail.getVdPpId() != null) {
                WmsPreparationPlan preparationPlan = wmsPreparationPlanMapper.selectByPrimaryKey(wmsPreparationVehicleDetail.getVdPpId());
                if (preparationPlan != null) {
                    WmsShipmentPlan wmsShipmentPlan = wmsShipmentPlanService.getShipmentByMateriaCodeAndColorAndVehicel(preparationPlan.getPpMaterialCode(),
                            preparationPlan.getPpCarColour(),
                            preparationPlan.getPpVehicleName(),
                            whCode);
                    setOterInfo(wmsShipmentPlan, wmsOutboundTask);
                }
            }
        } else if (WarehouseEnum.UNLCN_XN_CQ.getWhCode().equals(whCode)) {
            //重庆库
            if (StringUtils.isNotBlank(wmsPreparationVehicleDetail.getVdVin())) {
                WmsShipmentPlan wmsShipmentPlan = wmsShipmentPlanService.getShipmentPlanByVin(wmsPreparationVehicleDetail.getVdVin());
                setOterInfo(wmsShipmentPlan, wmsOutboundTask);
            }
        }
        wmsOutboundTask.setGmtCreate(new Date());
        wmsOutboundTask.setGmtModify(new Date());
        return wmsOutboundTask;
    }

    /**
     * * 发运变更 - 备料增车
     */
    @Override
    public void updateShipToPreparePlan(Long ppId) {
        //增车
        LOGGER.info("WmsPreparationPlanServiceImpl.updateShipToPreparePlan ppId: {}", ppId);
        //根据备料编号获取备料计划
        WmsPreparationPlan wmsPreparationPlan = getWmsPreparationPlanListByIdiaNo(ppId);

        //根据备料计划的指令号获取发运计划
        List<WmsShipmentPlan> wmsShipmentPlanList = getShipmentListByDispatchNo(wmsPreparationPlan.getPpGroupDispNo());
        //生成备料详情和任务
        addDetail(wmsShipmentPlanList, wmsPreparationPlan);
    }

    /**
     * 发运变更 - 剔除
     */
    @Override
    public void deletePreparetionDetail(Long vdId) {
        LOGGER.info("WmsPreparationPlanServiceImpl.deletePreparetionDetail vdId: {}", vdId);
        if (vdId == null) {
            throw new BusinessException("参数为空");
        }
        //获取备料详情数据
        WmsPreparationVehicleDetail detail = wmsPreparationVehicleDetailMapper.selectByPrimaryKey(vdId);
        if (detail == null || detail.getVdPpId() == null) {
            throw new BusinessException("找不到对应的备料详情数据");
        }

        //获取对应的备料数据
        WmsPreparationPlan wmsPreparationPlan = wmsPreparationPlanMapper.selectByPrimaryKey(detail.getVdPpId());
        if (wmsPreparationPlan == null && StringUtils.isBlank(wmsPreparationPlan.getPpPreparationMaterialNo())) {
            throw new BusinessException("找不到对应的备料数据");
        }

        //判断发运计划
        WmsShipmentPlanExample shipmentPlanExample = new WmsShipmentPlanExample();
        shipmentPlanExample.createCriteria()
                .andSpDispatchNoEqualTo(wmsPreparationPlan.getPpGroupDispNo())
                .andSpVinEqualTo(detail.getVdVin());
        List<WmsShipmentPlan> wmsShipmentPlanList = wmsShipmentPlanMapper.selectByExample(shipmentPlanExample);
        if (CollectionUtils.isEmpty(wmsShipmentPlanList)) {
            throw new BusinessException("找不到对应的发运计划");
        }
        WmsShipmentPlan wmsShipmentPlan = wmsShipmentPlanList.get(0);
        if (!WmsShipmentPlanModifyTypeEnum.DELETE.getValue().equals(wmsShipmentPlan.getOldModifyType())) {
            throw new BusinessException("对应的发运计划非变更删除");
        }

        //根据备料单号去获取对应的任务数据
        WmsOutboundTaskExample outboundTaskExample = new WmsOutboundTaskExample();
        outboundTaskExample.createCriteria()
                .andOtVinEqualTo(detail.getVdVin())
                .andOtPreparationMaterialNoEqualTo(wmsPreparationPlan.getPpPreparationMaterialNo());
        List<WmsOutboundTask> outboundTaskList = wmsOutboundTaskMapper.selectByExample(outboundTaskExample);
        //如果已经有任务
        if (CollectionUtils.isNotEmpty(outboundTaskList)) {
            WmsOutboundTask outboundTask = outboundTaskList.get(0);
            if (String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_NEW.getValue()).equals(outboundTask.getOtStatus())
                    || String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_READY.getValue()).equals(outboundTask.getOtStatus())) {
                //还没有产生任务, 则直接逻辑删除对应的备料详情
                detail.setIsDeleted(DeleteFlagEnum.DELETED.getValue());
                detail.setGmtUpdate(new Date());
                wmsPreparationVehicleDetailMapper.updateByPrimaryKeySelective(detail);
            } else {
                throw new BusinessException("已产生备料任务且非未领取/待开始, 不可直接剔除, 请做备料任务变更操作");
            }
        } else {
            //还没有产生任务, 则直接逻辑删除对应的备料详情
            detail.setIsDeleted(DeleteFlagEnum.DELETED.getValue());
            detail.setGmtUpdate(new Date());
            wmsPreparationVehicleDetailMapper.updateByPrimaryKeySelective(detail);
        }
    }

    /**
     * 发运变更 - 任务
     */
    @Override
    public void updateShipmentToTask(Long ppId, String whCode) {
        LOGGER.info("WmsPreparationPlanServiceImpl.updateShipmentToTask ppId: {}", ppId);
        WmsPreparationPlan wmsPreparationPlan = getWmsPreparationPlanListByIdiaNo(ppId);
        //前置校验 - 发运计划中的新增和减车是否都已处理
        if (String.valueOf(WmsPreparationPlanEnum.WMS_PLAN_NEW.getValue()).equals(wmsPreparationPlan.getPpStatus())) {
            throw new BusinessException("未开始的计划的不可变更");
        }
        queryPlanIsDeal(wmsPreparationPlan, wmsPreparationPlan.getPpGroupDispNo());

        //根据备料计划的指令号获取发运计划
        List<WmsShipmentPlan> wmsShipmentPlanList = getShipmentListByDispatchNo(wmsPreparationPlan.getPpGroupDispNo());
        if (CollectionUtils.isNotEmpty(wmsShipmentPlanList)) {
            for (WmsShipmentPlan wmsShipmentPlan : wmsShipmentPlanList) {
                if (wmsPreparationPlan != null && StringUtils.isNotBlank(wmsShipmentPlan.getSpVin())) {
                    //新增 - 增加任务
                    if (WmsShipmentPlanModifyTypeEnum.ADD.getValue().equals(wmsShipmentPlan.getOldModifyType())) {
                        WmsPreparationVehicleDetail detail = getDetail(wmsPreparationPlan.getPpId(), wmsShipmentPlan.getSpVin());
                        if (detail != null) {
                            //判断任务是否已经存在
                            boolean resultBoolean = queryOutboundTask(detail, wmsPreparationPlan);
                            if (!resultBoolean) {
                                wmsOutboundTaskMapper.insertSelective(addNewTask(detail, wmsPreparationPlan));
                            }
                        }
                    } else if (WmsShipmentPlanModifyTypeEnum.DELETE.getValue().equals(wmsShipmentPlan.getOldModifyType())) {
                        //删除的对任务进行判断
                        WmsOutboundTaskExample outboundTaskExample = new WmsOutboundTaskExample();
                        outboundTaskExample.createCriteria()
                                .andOtVinEqualTo(wmsShipmentPlan.getSpVin())
                                .andOtPreparationMaterialNoEqualTo(wmsPreparationPlan.getPpPreparationMaterialNo());
                        List<WmsOutboundTask> outboundTaskList = wmsOutboundTaskMapper.selectByExample(outboundTaskExample);
                        if (CollectionUtils.isNotEmpty(outboundTaskList)) {
                            //有任务的
                            WmsOutboundTask outboundTask = outboundTaskList.get(0);
                            //未完成的取消
                            if (String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_NEW.getValue()).equals(outboundTask.getOtStatus())
                                    || String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_READY.getValue()).equals(outboundTask.getOtStatus())) {
                                outboundTask.setOtStatus(String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_CANCLE.getValue()));
                                outboundTask.setGmtModify(new Date());
                                wmsOutboundTaskMapper.updateByPrimaryKeySelective(outboundTask);

                                //更新备料详情为逻辑删除
                                WmsPreparationVehicleDetail detailByVinAndMaertCode = getDetailByVinAndMaertCode(outboundTask.getOtVin(), outboundTask.getOtPreparationMaterialNo());
                                if (detailByVinAndMaertCode != null) {
                                    detailByVinAndMaertCode.setIsDeleted(DeleteFlagEnum.DELETED.getValue());
                                    detailByVinAndMaertCode.setGmtUpdate(new Date());
                                    wmsPreparationVehicleDetailMapper.updateByPrimaryKeySelective(detailByVinAndMaertCode);
                                }
                            }
                            //else if (String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_FINISHED.getValue()).equals(outboundTask.getOtStatus())
                            //        || String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_GOING.getValue()).equals(outboundTask.getOtStatus())) {
                            //    //已经完成的任务就需要退库
                            //    outboundTask.setOtQuitFlag(TaskQuitFlagEnum.HAS_QUIT.getValue());
                            //    outboundTask.setGmtModify(new Date());
                            //    wmsOutboundTaskMapper.updateByPrimaryKeySelective(outboundTask);
                            //    addInventory(outboundTask, whCode);
                            //}
                        }
                    }
                }
            }
        }
    }

    /**
     * 2017/12/25  新需求:到重庆前置库中转的车辆需要支持手动创建备料计划
     *
     * @param dto 参数封装对象
     * @return 返回值
     */
    @Override
    public ResultDTOWithPagination<List<WmsPreparationPlanResultDTO>> getStockTransferList(WmsPreparationPlanDTO dto) {
        LOGGER.info("WmsPreparationPlanServiceImpl.getStockTransferList param: {}", dto);
        if (Objects.equals(dto, null))
            throw new BusinessException("传入参数为空!");
        if (StringUtils.isBlank(dto.getWhCode()))
            throw new BusinessException("仓库code不能为空");
        if (StringUtils.isBlank(dto.getUserId()))
            throw new BusinessException("用户Id不能为空");
        if (!WhCodeEnum.UNLCN_XN_CQ.getValue().equals(dto.getWhCode()))
            throw new BusinessException("该仓库不支持该操作");
        //SysUser sysUser = sysUserMapper.selectByPrimaryKey(Integer.valueOf(dto.getUserId()));
        HashMap<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("type", WmsInboundOrderStockTransferEnum.STOCK_NOTCQ.getCode());
        paramMap.put("status", StringUtils.isBlank(dto.getStatus()) ? WmsInboundOrderStockTransferEnum.ST_STATUS_NOTDEAL.getCode() : dto.getStatus());
        paramMap.put("orderNo", dto.getOrderno());
        paramMap.put("customerName", StringUtils.isBlank(dto.getCustomerName()) ? "" : "%" + dto.getCustomerName());
        paramMap.put("startTime", dto.getStartTime());
        paramMap.put("endTime", dto.getEndTime());
        paramMap.put("notDel", DeleteFlagEnum.NORMAL.getValue());
        paramMap.put("limitStart", dto.getStartIndex() < 0 ? 0 : dto.getStartIndex());
        paramMap.put("limitEnd", dto.getPageSize());
        paramMap.put("orderBy", StringUtils.isBlank(dto.getOrder()) ? "a.odd_id desc" : "a." + dto.getOrder());
        paramMap.put("vin", dto.getVin());
        List<WmsPreparationPlanResultDTO> resultDTOS = wmsPreparationPlanExtMapper.selectStockTransferList(paramMap);
        if (CollectionUtils.isEmpty(resultDTOS))
            throw new BusinessException("未查询到符合要求的数据");
        int count = wmsPreparationPlanExtMapper.selectStockTransferCount(paramMap);
        PageVo pageVo = new PageVo();
        pageVo.setTotalRecord(count);
        pageVo.setOrder(dto.getOrder());
        pageVo.setPageNo(dto.getPageNo());
        pageVo.setPageSize(dto.getPageSize());
        ResultDTOWithPagination<List<WmsPreparationPlanResultDTO>> result = new ResultDTOWithPagination<>();
        result.setData(resultDTOS);
        result.setPageVo(pageVo);
        return result;
    }

    @Autowired
    private WmsInboundOrderDetailExtMapper wmsInboundOrderDetailExtMapper;

    /**
     * 2017/12/25  新需求:到重庆前置库中转的车辆需要支持手动创建备料计划
     * <p>
     * 保存手动创建的备料计划
     *
     * @param dto 参数封装
     */
    @Override
    public void savePreparationPlanStockTransfer(WmsPreparationPlanDTO dto) {
        LOGGER.info("WmsPreparationPlanServiceImpl.savePreparationPlanStockTransfer param: {}", dto);
        if (Objects.equals(dto, null))
            throw new BusinessException("传入参数为空!");
        if (StringUtils.isBlank(dto.getWhCode()))
            throw new BusinessException("仓库code不能为空");
        if (StringUtils.isBlank(dto.getUserId()))
            throw new BusinessException("用户Id不能为空");
        if (StringUtils.isBlank(dto.getOddIds()))
            throw new BusinessException("请勾选要生成备料计划的车辆(可一单多车)");
        if (StringUtils.isBlank(dto.getEstimateLoadingTime()))
            throw new BusinessException("请填写预计装车时间");
        if (StringUtils.isBlank(dto.getEstimateFinishTime()))
            throw new BusinessException("请填写预计装车完成时间");
        if (StringUtils.isBlank(dto.getCarrier()))
            throw new BusinessException("请填写承运商信息");
        if (StringUtils.isBlank(dto.getVehiclePlate()))
            throw new BusinessException("请填写承运车牌号");
        if (!WhCodeEnum.UNLCN_XN_CQ.getValue().equals(dto.getWhCode()))
            throw new BusinessException("该仓库不支持该操作");
        //处理参数
        String oddIds = dto.getOddIds();
        String subIds = null;
        if (oddIds.endsWith(",")) {
            subIds = oddIds.substring(0, oddIds.length() - 1);
        } else {
            subIds = oddIds;
        }
        String[] str_ids = subIds.split(",");
        ArrayList<Long> ids = Lists.newArrayList();
        Arrays.stream(str_ids).forEach(v -> {
            ids.add(Long.valueOf(v));
        });
        //更新orderdetail的状态
        SysUser sysUser = sysUserMapper.selectByPrimaryKey(Integer.valueOf(dto.getUserId()));

        List<WmsPreparationPlanResultDTO> details = wmsPreparationPlanExtMapper.selectStockTransferListByIds(ids);
        if (CollectionUtils.isNotEmpty(details)) {
            details.forEach(v -> {
                if (WmsInboundOrderStockTransferEnum.ST_STATUS_DEALED.getCode().equals(v.getOddStockTransferStatus())) {
                    throw new BusinessException("该车架号" + v.getOddVin() + "已经生成了备料计划,不能再进行该操作");
                }
            });
        }

        wmsInboundOrderDetailExtMapper.updateWmsOrderDeatailBatch(details);

        //生成备料计划
        WmsPreparationPlan plan = new WmsPreparationPlan();
        plan.setPpWhName(WhCodeEnum.UNLCN_XN_CQ.getText());
        plan.setPpWhCode(WhCodeEnum.UNLCN_XN_CQ.getValue());
        plan.setGmtCreate(new Date());
        plan.setGmtUpdate(new Date());
        plan.setCreateUserName(sysUser.getName());
        plan.setPpOperationStaff(sysUser.getName());
        plan.setPpStatus(WmsPreparationPlanEnum.WMS_PLAN_NEW.getValue() + "");
        plan.setPpCarrier(dto.getCarrier());
        plan.setPpSupplierVehiclePlate(dto.getVehiclePlate());
        plan.setPpVehicleName("手动创建备料计划");
        plan.setPpGroupDispNo("");
        plan.setIsDeleted(DeleteFlagEnum.NORMAL.getValue());
        SimpleDateFormat sdf = new SimpleDateFormat(DateUtils.FORMAT_DATETIME);
        try {
            plan.setPpEstimateFinishTime(sdf.parse(dto.getEstimateFinishTime()));
        } catch (ParseException e) {
            LOGGER.error("WmsShipmentPlanServiceImpl.savePreparationPlanStockTransfer error : ", e);
        }
        try {
            plan.setPpEstimateLoadingTime(sdf.parse(dto.getEstimateLoadingTime()));
        } catch (ParseException e) {
            LOGGER.error("WmsShipmentPlanServiceImpl.savePreparationPlanStockTransfer error : ", e);
        }
        wmsPreparationPlanMapper.insertSelective(plan);
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMdd");
        String today = sdf1.format(new Date());
        String no = "P" + today + "_" + plan.getPpId();
        plan.setPpPreparationMaterialNo(no);
        wmsPreparationPlanMapper.updateByPrimaryKeySelective(plan);
        //关联备料计划明细
        details.forEach(v -> {
            //创建备料计划明细
            WmsPreparationVehicleDetail wmsPreparationVehicleDetail = new WmsPreparationVehicleDetail();
            wmsPreparationVehicleDetail.setCreateUserName(sysUser.getName());
            wmsPreparationVehicleDetail.setModifyUserName(sysUser.getName());
            wmsPreparationVehicleDetail.setGmtCreate(new Date());
            wmsPreparationVehicleDetail.setGmtUpdate(new Date());
            wmsPreparationVehicleDetail.setIsDeleted(DeleteFlagEnum.NORMAL.getValue());
            wmsPreparationVehicleDetail.setVdOutstockStatus(null);
            wmsPreparationVehicleDetail.setVdPpId(plan.getPpId());
            wmsPreparationVehicleDetail.setVdVehicleDesc(v.getOddVehicleSpecDesc());
            wmsPreparationVehicleDetail.setVdVehicleName(v.getOddVehicleSpecName());
            wmsPreparationVehicleDetail.setVdVin(v.getOddVin());
            wmsPreparationVehicleDetail.setVdWaybillNo(v.getOdOrderno());
            wmsPreparationVehicleDetail.setVersions(null);
            wmsPreparationVehicleDetail.setVdOutstockStatus(WmsOutboundStatusEnum.WMS_OUTBOUND_NEW.getValue() + "");
            wmsPreparationVehicleDetailMapper.insertSelective(wmsPreparationVehicleDetail);
        });


    }

    /**
     * 动态获取客户名称列表
     * 2017/12/25  新需求:到重庆前置库中转的车辆需要支持手动创建备料计划
     * <p>
     * 保存手动创建的备料计划
     *
     * @param dto 参数封装
     */
    @Override
    public List<WmsPreparationPlanResultDTO> getCustomerNameList(WmsPreparationPlanDTO dto) {
        LOGGER.info("WmsPreparationPlanServiceImpl.getCustomerNameList param: {}", dto);
        if (Objects.equals(dto, null))
            throw new BusinessException("传入参数为空!");
        if (StringUtils.isBlank(dto.getWhCode()))
            throw new BusinessException("仓库code不能为空");
        if (StringUtils.isBlank(dto.getUserId()))
            throw new BusinessException("用户Id不能为空");
        HashMap<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("notDel", DeleteFlagEnum.NORMAL.getValue());
        paramMap.put("type", WmsInboundOrderStockTransferEnum.STOCK_NOTCQ.getCode());
        return wmsPreparationPlanExtMapper.selectStockTransferCustomerList(paramMap);
    }

    /**
     * * 动态获取客户名称下拉框接口
     * <p>2017-12-28 备料计划的数据导出</p>
     *
     * @param dto 参数map
     */
    @Override
    public HSSFWorkbook getImportExcelData(WmsPreparationPlanDTO dto) {
        LOGGER.info("WmsPreparationPlanServiceImpl.getImportExcelData param:{}", dto);
        if (Objects.equals(dto, null))
            throw new BusinessException("传入参数为空!");
        if (StringUtils.isBlank(dto.getWhCode()))
            throw new BusinessException("仓库code为空");
        if (StringUtils.isBlank(dto.getUserId()))
            throw new BusinessException("用户id为空");
        HashMap<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("ppWhCode", dto.getWhCode());
        paramMap.put("vdVin", dto.getVin());
        paramMap.put("ppOrderNo", dto.getPpOrderNo());
        paramMap.put("ppEstimateLane", dto.getPpEstimateLane());
        paramMap.put("ppPreparationMaterialNo", dto.getPpPreparationMaterialNo());
        paramMap.put("gmtCreateStart", dto.getGmtCreateStart());
        paramMap.put("gmtCreateEnd", dto.getGmtCreateEnd());
        paramMap.put("ppStatus", dto.getPpStatus());
        paramMap.put("orderBy", StringUtils.isBlank(dto.getOrder()) ? "gmt_create desc" : dto.getOrder());
        List<WmsPreparationPlan> planList = wmsPreparationPlanExtMapper.queryForListNew(paramMap);
        SysUser sysUser = sysUserMapper.selectByPrimaryKey(Integer.valueOf(dto.getUserId()));
        String name = "";
        if (sysUser != null) {
            name = sysUser.getName();
        }
        ArrayList<WmsPreparationPlanBO> planBos = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(planList)) {
            String finalName = name;
            planList.forEach(v -> {
                WmsPreparationPlanBO bo = new WmsPreparationPlanBO();
                BeanUtils.copyProperties(v, bo);
                bo.setPpOperationStaff(StringUtils.isNotBlank(v.getPpOperationStaff()) ? v.getPpOperationStaff() : finalName);
                bo.setGmtCreate(v.getGmtCreate() != null ? sdf.format(v.getGmtCreate()) : "");
                bo.setPpEstimateLoadingTime(v.getPpEstimateLoadingTime() != null ? sdf.format(v.getPpEstimateLoadingTime()) : "");
                bo.setPpEstimateFinishTime(v.getPpEstimateFinishTime() != null ? sdf.format(v.getPpEstimateFinishTime()) : "");
                //重庆库  备料计划列表页面增加显示板车实际入场时间/出场时间
                updateSetGateInOutTime(paramMap, v, bo);
                planBos.add(bo);
            });
            //1.导出excel头  备料编号	发运指令号	备料员	创建时间	计划装车道	计划装车时间	预计完成时间	实际进场时间	实际出场时间	备料状态
            String[] heads = new String[]{
                    "备料编号", "发运指令号", "备料员", "创建时间", "计划装车道", "计划装车时间",
                    "预计完成时间", "实际进场时间", "实际出场时间", "备料状态"};
            String title = "备料计划数据导出";
            return updateExportToExcel(title, heads, planBos, "yyyy-MM-dd HH:mm:ss");
        }
        return null;
    }

    /**
     * 设置板车实际进出场时间
     *
     * @param paramMap 参数map
     * @param v        备料计划对象
     * @param bo       参数返回对象
     */
    private void updateSetGateInOutTime(Map<String, Object> paramMap, WmsPreparationPlan v, WmsPreparationPlanBO bo) {
        if (!Objects.equals(paramMap.get("ppWhCode"), null)
                && WhCodeEnum.UNLCN_XN_CQ.getValue().equals(paramMap.get("ppWhCode").toString())
                && StringUtils.isNotBlank(v.getPpGroupDispNo())) {
            //关联查询板车出入场记录表--根据指令号
            HashMap<String, Object> ppMap = Maps.newHashMap();
            ppMap.put("shipNo", v.getPpGroupDispNo());
            ppMap.put("status", WmsDepartureOpenStatusEnum.OPENED.getValue());
            ppMap.put("inoutType", WmsGateControllerTypeEnum.GATE_IN.getCode());
            ppMap.put("orderBy", "dr_id desc");
            ppMap.put("start", 0);
            ppMap.put("end", 1);
            List<WmsDepartureRegister> inList = wmsDepartureRegisterExtMapper.selectListByParam(ppMap);
            if (CollectionUtils.isNotEmpty(inList)) {
                Date drDepartureTime = inList.get(0).getDrDepartureTime();
                if (!Objects.equals(drDepartureTime, null)) {
                    bo.setPpGateInTime(DateUtils.getStringFromDate(drDepartureTime, DateUtils.FORMAT_DATETIME));
                }
            }
            ppMap.put("inoutType", WmsGateControllerTypeEnum.GATE_OUT.getCode());
            List<WmsDepartureRegister> outList = wmsDepartureRegisterExtMapper.selectListByParam(ppMap);
            if (CollectionUtils.isNotEmpty(outList)) {
                Date drDepartureTime = outList.get(0).getDrDepartureTime();
                if (!Objects.equals(drDepartureTime, null)) {
                    bo.setPpGateOutTime(DateUtils.getStringFromDate(drDepartureTime, DateUtils.FORMAT_DATETIME));
                }
            }
        }
    }


    /**
     * @param title   sheet标题
     * @param headers 表头
     * @param planBOS 订单跟踪对象
     * @param pattern @Title exportExcel
     */
    private HSSFWorkbook updateExportToExcel(String title,
                                             String[] headers,
                                             List<WmsPreparationPlanBO> planBOS,
                                             String pattern) {
        // 声明一个工作薄
        HSSFWorkbook workbook = new HSSFWorkbook();
        // 生成一个表格
        HSSFSheet sheet = workbook.createSheet(title);
        // 设置表格默认列宽度为15个字节
        sheet.setDefaultColumnWidth((short) 20);
        // 生成一个样式
        HSSFCellStyle style = workbook.createCellStyle();
        // 设置这些样式
        style.setFillForegroundColor(HSSFColor.SKY_BLUE.index);
        style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);//上下居中
        style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        style.setBorderRight(HSSFCellStyle.BORDER_THIN);
        style.setBorderTop(HSSFCellStyle.BORDER_THIN);
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        // 生成一个字体
        HSSFFont font = workbook.createFont();
        font.setColor(HSSFColor.VIOLET.index);
        font.setFontHeightInPoints((short) 12);
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        // 把字体应用到当前的样式
        style.setFont(font);
        // 生成并设置另一个样式
        HSSFCellStyle style2 = workbook.createCellStyle();
        style2.setFillForegroundColor(HSSFColor.WHITE.index);
        style2.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        style2.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        style2.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        style2.setBorderRight(HSSFCellStyle.BORDER_THIN);
        style2.setBorderTop(HSSFCellStyle.BORDER_THIN);
        style2.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        style2.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        // 生成另一个字体
        HSSFFont font2 = workbook.createFont();
        font2.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
        // 把字体应用到当前的样式
        style2.setFont(font2);

        // 产生表格标题行
        HSSFRow row = sheet.createRow(0);
        for (short i = 0; i < headers.length; i++) {
            HSSFCell cell = row.createCell(i);
            cell.setCellStyle(style);
            HSSFRichTextString text = new HSSFRichTextString(headers[i]);
            cell.setCellValue(text);
        }

        // 遍历集合数据，产生数据行
        Iterator<WmsPreparationPlanBO> iterator = planBOS.iterator();
        int index = 0;
        while (iterator.hasNext()) {
            index++;
            row = sheet.createRow(index);//创建行
            WmsPreparationPlanBO next = iterator.next();
            //对应头  设置cell的值
            for (short i = 0; i < headers.length; i++) {
                HSSFCell cell = row.createCell(i);
                cell.setCellStyle(style2);
                //1.导出excel头  备料编号	发运指令号	备料员	创建时间	计划装车道	计划装车时间	预计完成时间	实际进场时间	实际出场时间	备料状态
                switch (i) {
                    case 0: {
                        cell.setCellValue(updateSetCellValue(next.getPpPreparationMaterialNo()));
                        break;
                    }
                    case 1: {
                        cell.setCellValue(updateSetCellValue(next.getPpGroupDispNo()));
                        break;
                    }
                    case 2: {
                        cell.setCellValue(updateSetCellValue(next.getPpOperationStaff()));
                        break;
                    }
                    case 3: {
                        cell.setCellValue(updateSetCellValue(next.getGmtCreate()));
                        break;
                    }
                    case 4: {
                        cell.setCellValue(updateSetCellValue(next.getPpEstimateLane()));
                        break;
                    }
                    case 5: {
                        cell.setCellValue(updateSetCellValue(next.getPpEstimateLoadingTime()));
                        break;
                    }
                    case 6: {
                        cell.setCellValue(updateSetCellValue(next.getPpEstimateFinishTime()));
                        break;
                    }
                    case 7: {
                        cell.setCellValue(updateSetCellValue(next.getPpGateInTime()));
                        break;
                    }
                    case 8: {
                        cell.setCellValue(updateSetCellValue(next.getPpGateOutTime()));
                        break;
                    }
                    case 9: {
                        if (StringUtils.isNotBlank(next.getPpStatus())) {
                            WmsPreparationPlanEnum planEnum = WmsPreparationPlanEnum.getByValue(Integer.valueOf(next.getPpStatus()));
                            if (planEnum != null) {
                                cell.setCellValue(updateSetCellValue(planEnum.getText()));
                            }
                        }
                        break;
                    }
                    default:
                        break;
                }
            }
        }
        return workbook;
    }

    /**
     * 判断字符串设置值--非空过滤
     */
    private String updateSetCellValue(Object object) {
        if (!Objects.equals(object, null)) {
            String value = object.toString();
            if (StringUtils.isNotBlank(value)) {
                return value;
            }
        }
        return "";
    }

    /**
     * 时间格式化--非空过滤
     */
    private String getFormatDate(Date date) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (date != null) {
            return sdf.format(date);
        }
        return "";
    }


    /**
     * 发运任务变更 - 校验备料详情是否已经处理
     */
    private void queryPlanIsDeal(WmsPreparationPlan wmsPreparationPlan, String dispatchNo) {
        //判断发运加护是否有变更
        WmsShipmentPlanExample checkShipmentPlanExample = new WmsShipmentPlanExample();
        WmsShipmentPlanExample.Criteria criteria = checkShipmentPlanExample.createCriteria();
        criteria.andSpDispatchNoEqualTo(dispatchNo);
        int allCount = wmsShipmentPlanMapper.countByExample(checkShipmentPlanExample);

        criteria.andOldModifyTypeIsNull();
        int notChangeCount = wmsShipmentPlanMapper.countByExample(checkShipmentPlanExample);
        if (allCount == notChangeCount) {
            throw new BusinessException("未有需要变更的发运计划");
        }

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("spDispatchNo", dispatchNo);
        paramMap.put("spSendBusinessFlag", SendBusinessFlagEnum.SEND_N.getValue());
        paramMap.put("oldModifyTypeNotEquals", WmsShipmentPlanModifyTypeEnum.DELETE.getValue());
        Integer notDealCount = wmsShipmentPlanExtMapper.countShipmentForUpdtePlan(paramMap);
        if (notDealCount > 0) {
            throw new BusinessException("存在未处理的发运计划, 请先处理");
        }

        //查看已处理的发运计划
        WmsShipmentPlanExample shipmentPlanExample = new WmsShipmentPlanExample();
        shipmentPlanExample.createCriteria()
                .andSpSendBusinessFlagEqualTo(String.valueOf(SendBusinessFlagEnum.SEND_Y.getValue()))
                .andSpDispatchNoEqualTo(dispatchNo);
        List<WmsShipmentPlan> wmsShipmentPlanList = wmsShipmentPlanMapper.selectByExample(shipmentPlanExample);
        //校验发运计划
        checkShipmentList(wmsShipmentPlanList, wmsPreparationPlan);
        //List<WmsPreparationVehicleDetail> vehicleDetailList = wmsPreparationPlanExtMapper.getVehicleDetail(wmsPreparationPlan.getPpId(), DeleteFlagEnum.HAS_QUIT.getValue());
        //List<String> vinList = new ArrayStack();
        //if (CollectionUtils.isNotEmpty(vehicleDetailList)) {
        //    vehicleDetailList.stream()
        //            .filter(detail -> detail != null && StringUtils.isNotBlank(detail.getVdVin()))
        //            .forEach(detail -> {
        //                vinList.add(detail.getVdVin());
        //            });
        //    WmsShipmentPlanExample queryCheckEeample = new WmsShipmentPlanExample();
        //    queryCheckEeample.createCriteria()
        //            .andSpVinIn(vinList);
        //    List<WmsShipmentPlan> queryCheckShipList = wmsShipmentPlanMapper.selectByExample(shipmentPlanExample);
        //    checkShipmentList(queryCheckShipList, wmsPreparationPlan);
        //}
    }

    /**
     * 发运计划校验是否完成
     */
    private void checkShipmentList(List<WmsShipmentPlan> wmsShipmentPlanList,
                                   WmsPreparationPlan wmsPreparationPlan) {
        if (CollectionUtils.isNotEmpty(wmsShipmentPlanList)) {
            int allUpdateCount = 0;
            int notUpdateCount = 0;
            for (WmsShipmentPlan wmsShipmentPlan : wmsShipmentPlanList) {
                if (WmsShipmentPlanModifyTypeEnum.DELETE.getValue().equals(wmsShipmentPlan.getOldModifyType())) {
                    //未产生任务的状态下, 判断备料详情是否已逻辑删除
                    WmsOutboundTaskExample outboundTaskExample = new WmsOutboundTaskExample();
                    outboundTaskExample.createCriteria()
                            .andOtVinEqualTo(wmsShipmentPlan.getSpVin())
                            .andOtPreparationMaterialNoEqualTo(wmsPreparationPlan.getPpPreparationMaterialNo());
                    List<WmsOutboundTask> outboundTaskList = wmsOutboundTaskMapper.selectByExample(outboundTaskExample);
                    //如果已经有任务
                    if (CollectionUtils.isEmpty(outboundTaskList)) {
                        //判断备料详情是否逻辑删除
                        WmsPreparationVehicleDetail detail = getDetailForAllDelete(wmsPreparationPlan.getPpId(), wmsShipmentPlan.getSpVin());
                        if (detail != null
                                && !String.valueOf(DeleteFlagEnum.DELETED.getValue()).equals(String.valueOf(detail.getIsDeleted()))) {
                            throw new BusinessException("存在未剔除的发运计划, 请先删除");
                        } else {
                            notUpdateCount++;
                        }
                        allUpdateCount++;
                    } else {
                        WmsOutboundTask outboundTask = outboundTaskList.get(0);
                        if (outboundTask != null) {
                            if (String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_NEW.getValue()).equals(outboundTask.getOtStatus())
                                    || String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_READY.getValue()).equals(outboundTask.getOtStatus())) {
                                WmsPreparationVehicleDetail detail = getDetailForAllDelete(wmsPreparationPlan.getPpId(), wmsShipmentPlan.getSpVin());
                                if (detail != null
                                        && !String.valueOf(DeleteFlagEnum.DELETED.getValue()).equals(String.valueOf(detail.getIsDeleted()))) {
                                    throw new BusinessException("存在未剔除的发运计划, 请先删除");
                                } else {
                                    notUpdateCount++;
                                }
                                allUpdateCount++;
                            }
                        }
                    }
                } else if (WmsShipmentPlanModifyTypeEnum.ADD.getValue().equals(wmsShipmentPlan.getOldModifyType())) {
                    //判断任务是否已经
                    WmsPreparationVehicleDetail detail = getDetail(wmsPreparationPlan.getPpId(), wmsShipmentPlan.getSpVin());
                    if (detail == null) {
                        throw new BusinessException("存在未增车的发运计划, 请先增车");
                    } else {
                        boolean resultBoolean = queryOutboundTask(detail, wmsPreparationPlan);
                        if (resultBoolean) {
                            notUpdateCount++;
                        }
                        allUpdateCount++;
                    }

                }
            }
            if (allUpdateCount != 0 && notUpdateCount == allUpdateCount) {
                throw new BusinessException("未有需要变更的任务");
            }
        }
    }


    /**
     * 判断是否存在任务
     *
     * @return false-没有任务, true-已有任务
     */
    private boolean queryOutboundTask(WmsPreparationVehicleDetail wmsPreparationVehicleDetail,
                                      WmsPreparationPlan wmsPreparationPlan) {
        boolean resultBoolean = false;
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("otVin", wmsPreparationVehicleDetail.getVdVin());
        paramMap.put("otPreparationMaterialNo", wmsPreparationPlan.getPpPreparationMaterialNo());
        paramMap.put("isDeleted", DeleteFlagEnum.NORMAL.getValue());
        //非取消状态
        paramMap.put("otStatusNotEquals", String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_CANCLE.getValue()));
        //非退库状态
        paramMap.put("otQuitFlagNotEquals", TaskQuitFlagEnum.HAS_QUIT.getValue());
        Integer count = wmsOutboundTaskExtMapper.countTaskForShipUpdate(paramMap);
        if (count > 0) {
            resultBoolean = true;
        }
        return resultBoolean;
    }

    /**
     * 发运变更 - 新增入库记录
     */
    private void addInventory(WmsOutboundTask outboundTask, String whCode) {
        //获取老入库记录
        WmsInboundOrder oldInboundOrder = getOldInboundOrder(outboundTask.getOtVin());
        if (oldInboundOrder == null) {
            throw new BusinessException("该单没有入库记录, 请核实");
        }
        WmsInboundOrderDetailExample detailExample = new WmsInboundOrderDetailExample();
        detailExample.createCriteria().andOddOdIdEqualTo(oldInboundOrder.getOdId());
        List<WmsInboundOrderDetail> orderDetailList = inboundOrderDetailMapper.selectByExample(detailExample);
        if (CollectionUtils.isEmpty(orderDetailList)) {
            throw new BusinessException("该单没有入库记录, 请核实");
        }
        WmsInboundOrderDetail inboundOrderDetail = orderDetailList.get(0);

        WmsWarehouseBO wmsWarehouseBO = new WmsWarehouseBO();
        wmsWarehouseBO.setWhCode(whCode);
        WmsWarehouse warehouse = wmsWarehouseService.findWarehouseByCode(wmsWarehouseBO);

        //生成入库单wmsWarehouseService
        WmsInboundOrder insertOrder = new WmsInboundOrder();
        BeanUtils.copyProperties(oldInboundOrder, insertOrder);
        reSetOrderInfo(insertOrder);
        if (warehouse != null) {
            insertOrder.setOdWhCode(warehouse.getWhCode());
            insertOrder.setOdWhName(warehouse.getWhName());
            insertOrder.setOdWhId(warehouse.getWhId());
        }
        wmsInboundOrderMapper.insertSelective(insertOrder);

        //老数据逻辑删除
        oldInboundOrder.setIsDeleted(DeleteFlagEnum.DELETED.getValue());
        oldInboundOrder.setGmtUpdate(new Date());
        wmsInboundOrderMapper.updateByPrimaryKeySelective(oldInboundOrder);

        //入库详情
        WmsInboundOrderDetail insertDetail = new WmsInboundOrderDetail();
        BeanUtils.copyProperties(inboundOrderDetail, insertDetail);
        insertDetail.setOddOdId(insertOrder.getOdId());
        reSetOrderDetailInfo(insertDetail);
        if (warehouse != null) {
            insertDetail.setOddWhCode(warehouse.getWhCode());
            insertDetail.setOddWhName(warehouse.getWhName());
        }
        inboundOrderDetailMapper.insertSelective(insertDetail);

        //入库详情看逻辑删除
        inboundOrderDetail.setIsDeleted(DeleteFlagEnum.DELETED.getValue());
        inboundOrderDetail.setGmtUpdate(new Date());
        inboundOrderDetailMapper.updateByPrimaryKeySelective(inboundOrderDetail);
    }

    /**
     * 发运变更 - 清空入库信息
     */
    private void reSetOrderInfo(WmsInboundOrder insertOrder) {
        insertOrder.setGmtCreate(new Date());
        insertOrder.setGmtUpdate(new Date());
        insertOrder.setOdStatus(String.valueOf(WmsInboundStatusEnum.WMS_INBOUND_CREATE.getValue()));
        insertOrder.setOdWaybillType(WmsSysSourceEnum.WMS_QUIT.getValue());
        insertOrder.setIsDeleted(DeleteFlagEnum.NORMAL.getValue());
    }

    /**
     * 清空入库详情信息
     */
    private void reSetOrderDetailInfo(WmsInboundOrderDetail insertDetail) {
        insertDetail.setGmtUpdate(new Date());
        //清空库位库存
        insertDetail.setOddWhLocName(null);
        insertDetail.setOddWhLocCode(null);
        insertDetail.setOddWhZoneCode(null);
        insertDetail.setOddWhZoneName(null);
        insertDetail.setIsDeleted(DeleteFlagEnum.NORMAL.getValue());//逻辑删除是正常
    }

    /**
     * 发运变更 - 获取老入库记录
     */
    private WmsInboundOrder getOldInboundOrder(String vin) {
        if (StringUtils.isNotBlank(vin)) {

            WmsInboundOrderDetailExample detailExample = new WmsInboundOrderDetailExample();
            detailExample.createCriteria().andOddVinEqualTo(vin);
            List<WmsInboundOrderDetail> detailList = inboundOrderDetailMapper.selectByExample(detailExample);
            if (CollectionUtils.isEmpty(detailList)) {
                throw new BusinessException("该单没有入库记录, 请核实");
            }

            List<Long> orderIdList = new ArrayList<>();
            detailList.stream()
                    .filter(detail -> detail != null && detail.getOddOdId() != null)
                    .forEach(detail -> orderIdList.add(detail.getOddOdId()));

            if (CollectionUtils.isEmpty(orderIdList)) {
                throw new BusinessException("该单没有入库记录, 请核实");
            }

            WmsInboundOrderExample example = new WmsInboundOrderExample();
            example.setOrderByClause(" od_id desc ");
            example.createCriteria()
                    .andOdIdIn(orderIdList)
                    .andOdWaybillTypeEqualTo(WmsSysSourceEnum.TMS.getValue());
            List<WmsInboundOrder> orderList = wmsInboundOrderMapper.selectByExample(example);
            if (CollectionUtils.isEmpty(orderList)) {
                throw new BusinessException("该单没有入库记录, 请核实");
            }

            return orderList.get(0);
        }
        return null;
    }


    /**
     * 发运变更 - 根据主表主键和车架号获取详情 - delete is normal
     */
    private WmsPreparationVehicleDetail getDetail(Long ppId, String vin) {
        WmsPreparationVehicleDetailExample detailExample = new WmsPreparationVehicleDetailExample();
        detailExample.setOrderByClause(" vd_id desc ");
        detailExample.createCriteria()
                .andVdVinEqualTo(vin)
                .andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue())
                .andVdPpIdEqualTo(ppId);
        List<WmsPreparationVehicleDetail> detailList = wmsPreparationVehicleDetailMapper.selectByExample(detailExample);
        if (CollectionUtils.isNotEmpty(detailList)) {
            return detailList.get(0);
        }
        return null;
    }

    /**
     * 发运变更 - 根据主表主键和车架号获取详情 - delete is normal
     */
    private WmsPreparationVehicleDetail getDetailForAllDelete(Long ppId, String vin) {
        WmsPreparationVehicleDetailExample detailExample = new WmsPreparationVehicleDetailExample();
        detailExample.setOrderByClause(" vd_id desc ");
        detailExample.createCriteria()
                .andVdVinEqualTo(vin)
                .andVdPpIdEqualTo(ppId);
        List<WmsPreparationVehicleDetail> detailList = wmsPreparationVehicleDetailMapper.selectByExample(detailExample);
        if (CollectionUtils.isNotEmpty(detailList)) {
            return detailList.get(0);
        }
        return null;
    }

    /**
     * 发运变更 - 根据车架号和备料单号备料计划
     */
    private WmsPreparationVehicleDetail getDetailByVinAndMaertCode(String vin, String ppMaterCode) {
        WmsPreparationPlanExample planExample = new WmsPreparationPlanExample();
        planExample.createCriteria().andPpPreparationMaterialNoEqualTo(ppMaterCode);
        List<WmsPreparationPlan> wmsPreparationPlanList = wmsPreparationPlanMapper.selectByExample(planExample);
        if (CollectionUtils.isNotEmpty(wmsPreparationPlanList) && wmsPreparationPlanList.get(0) != null) {

            WmsPreparationVehicleDetailExample detailExample = new WmsPreparationVehicleDetailExample();
            detailExample.createCriteria()
                    .andVdVinEqualTo(vin)
                    .andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue())
                    .andVdPpIdEqualTo(wmsPreparationPlanList.get(0).getPpId());
            List<WmsPreparationVehicleDetail> detailList = wmsPreparationVehicleDetailMapper.selectByExample(detailExample);
            if (CollectionUtils.isNotEmpty(detailList)) {
                return detailList.get(0);
            }
        }
        return null;
    }

    /**
     * 发运变更 - 生成备料详情和任务
     */
    private void addDetail(List<WmsShipmentPlan> wmsShipmentPlanList, WmsPreparationPlan wmsPreparationPlan) {
        //增加备料详情
        boolean isAddUpdate = false;
        WmsPreparationVehicleDetail detail = null;
        for (WmsShipmentPlan wmsShipmentPlan : wmsShipmentPlanList) {
            if (wmsPreparationPlan != null) {
                //如果是新增
                if (WmsShipmentPlanModifyTypeEnum.ADD.getValue().equals(wmsShipmentPlan.getOldModifyType())
                        && String.valueOf(SendBusinessFlagEnum.SEND_N.getValue()).equals(wmsShipmentPlan.getSpSendBusinessFlag())) {
                    //新增备料详情
                    detail = addPrepareDetail(wmsShipmentPlan, wmsPreparationPlan.getPpId());
                    wmsPreparationVehicleDetailMapper.insertSelective(detail);
                    //更新发运计划为已处理
                    wmsShipmentPlan.setSpSendBusinessFlag(String.valueOf(SendBusinessFlagEnum.SEND_Y.getValue()));
                    wmsShipmentPlanMapper.updateByPrimaryKeySelective(wmsShipmentPlan);
                    isAddUpdate = true;
                }
            }
        }
        if (!isAddUpdate) {
            throw new BusinessException("不存在未处理且需要新增的车辆");
        }
        if (String.valueOf(WmsPreparationPlanEnum.WMS_PLAN_FINISH.getValue()).equals(wmsPreparationPlan.getPpStatus())) {
            wmsPreparationPlan.setPpStatus(String.valueOf(WmsPreparationPlanEnum.WMS_PLAN_CONFIRM.getValue()));
            wmsPreparationPlanMapper.updateByPrimaryKeySelective(wmsPreparationPlan);
        }
        //如果备料计划有任务了则需要增加任务
        //if (!String.valueOf(WmsPreparationPlanEnum.WMS_PLAN_NEW.getValue()).equals(wmsPreparationPlan.getPpStatus())) {
        //    //新增任务
        //    if (detail != null) {
        //        //wmsOutboundTaskMapper.insertSelective(addNewTask(detail, wmsPreparationPlan));
        //        //如果备料已完成则回退状态到执行中
        //
        //    }
        //}
    }

    /**
     * 获取备料计划 - 获取备料详情
     * linbao 2017-11-15
     */
    private WmsPreparationPlan getWmsPreparationPlanListByIdiaNo(Long ppId) {
        WmsPreparationPlan preparationPlan = wmsPreparationPlanMapper.selectByPrimaryKey(ppId);
        if (preparationPlan == null) {
            throw new BusinessException("找不到对应的备料计划");
        }
        //不用校验 - 都需要增车
        return preparationPlan;
    }

    /**
     * 发运变更 - 获取发运计划
     * linbao 2017-11-15
     */
    private List<WmsShipmentPlan> getShipmentListByDispatchNo(String dispatchNo) {
        WmsShipmentPlanExample shipmentPlanExample = new WmsShipmentPlanExample();
        shipmentPlanExample.createCriteria().andSpDispatchNoEqualTo(dispatchNo);
        List<WmsShipmentPlan> wmsShipmentPlanList = wmsShipmentPlanMapper.selectByExample(shipmentPlanExample);
        if (CollectionUtils.isEmpty(wmsShipmentPlanList)) {
            throw new BusinessException("找不到相关发运计划数据");
        }
        //校验并获取增加的车

        return wmsShipmentPlanList;
    }

    /**
     * 发运变更 - 新增详情
     * linbao 2017-11-15
     */
    private WmsPreparationVehicleDetail addPrepareDetail(WmsShipmentPlan wmsShipmentPlan, Long ppId) {
        WmsPreparationVehicleDetail wmsPreparationVehicleDetail = new WmsPreparationVehicleDetail();
        wmsPreparationVehicleDetail.setCreateUserName("");
        wmsPreparationVehicleDetail.setGmtCreate(new Date());
        wmsPreparationVehicleDetail.setIsDeleted(DeleteFlagEnum.NORMAL.getValue());
        wmsPreparationVehicleDetail.setVdOutstockStatus(null);
        wmsPreparationVehicleDetail.setVdPpId(ppId);
        wmsPreparationVehicleDetail.setVdVehicleDesc(wmsShipmentPlan.getSpVehicleDesc());
        wmsPreparationVehicleDetail.setVdVehicleName(wmsShipmentPlan.getSpVehicleName());
        wmsPreparationVehicleDetail.setVdVin(wmsShipmentPlan.getSpVin());
        wmsPreparationVehicleDetail.setVdWaybillNo(wmsShipmentPlan.getSpWaybillNo());
        wmsPreparationVehicleDetail.setVersions(null);
        wmsPreparationVehicleDetail.setVdOutstockStatus(String.valueOf(WmsOutboundStatusEnum.WMS_OUTBOUND_NEW.getValue()));
        return wmsPreparationVehicleDetail;
    }


    /**
     * 设置主板获取发运类型和目的地
     */
    private void setOterInfo(WmsShipmentPlan wmsShipmentPlan, WmsOutboundTask wmsOutboundTask) {
        if (wmsShipmentPlan != null) {
            wmsOutboundTask.setOtCustomerName(wmsShipmentPlan.getSpCustomerName());
            wmsOutboundTask.setOtCustomerCode(wmsShipmentPlan.getSpCustomerCode());
            wmsOutboundTask.setOtType("");//出库类型
            wmsOutboundTask.setOtDest(wmsShipmentPlan.getSpDest());//目的地
        }
    }

    /**
     * 发运变更 - 新增新任务
     * linbao 2017-11-15
     */
    private WmsOutboundTask addNewTask(WmsPreparationVehicleDetail wmsPreparationVehicleDetail,
                                       WmsPreparationPlan wmsPreparationPlan) {
        //校验该车辆在库存表中是否存在
        WmsInventoryLocationExample inventoryLocationExample = new WmsInventoryLocationExample();
        WmsInventoryLocationExample.Criteria criteria = inventoryLocationExample.createCriteria();
        criteria.andInvlocVinEqualTo(wmsPreparationVehicleDetail.getVdVin());
        criteria.andIsDeletedNotEqualTo(DeleteFlagEnum.DELETED.getValue());
        List<WmsInventoryLocation> wmsInventoryLocations = wmsInventoryLocationMapper.selectByExample(inventoryLocationExample);
        if (CollectionUtils.isEmpty(wmsInventoryLocations)) {
            throw new BusinessException("该车辆:" + wmsPreparationVehicleDetail.getVdVin() + "不存在于库存中");
        }
        WmsOutboundTask wmsOutboundTask = new WmsOutboundTask();
        wmsOutboundTask.setOtPreparationMaterialNo(wmsPreparationPlan.getPpPreparationMaterialNo());//备料单号
        wmsOutboundTask.setOtVin(wmsPreparationVehicleDetail.getVdVin());//车架号(vin码)
        wmsOutboundTask.setOtVehicleSpecName(wmsPreparationVehicleDetail.getVdVehicleName());//车型
        AsnOrderDTO asnOrderDTO = wmsInboundAsnOrderAddMapper.queryByVin(wmsPreparationVehicleDetail.getVdVin());
        if (null != asnOrderDTO && !Objects.isNull(asnOrderDTO)) {
            wmsOutboundTask.setOtZoneCode(asnOrderDTO.getAsnOrderDetailDTOList().get(0).getOddWhZoneCode());
            wmsOutboundTask.setOtZoneName(asnOrderDTO.getAsnOrderDetailDTOList().get(0).getOddWhZoneName());
            wmsOutboundTask.setOtLocationCode(asnOrderDTO.getAsnOrderDetailDTOList().get(0).getOddWhLocCode());
            wmsOutboundTask.setOtLcoationName(asnOrderDTO.getAsnOrderDetailDTOList().get(0).getOddWhLocName());
        }
        wmsOutboundTask.setOtWaybillNo(wmsPreparationVehicleDetail.getVdWaybillNo());
        wmsOutboundTask.setOtEstimateLane(wmsPreparationPlan.getPpEstimateLane());//装车道
        wmsOutboundTask.setOtStatus(String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_NEW.getValue()));//状态-未领取
        wmsOutboundTask.setInspectStatus(WmsOutboundInspectStatusEnum.WAYBILL_INIT.getValue());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        wmsOutboundTask.setOtTaskNo("TA" + sdf.format(new Date()));//设置备料任务号
        wmsOutboundTask.setOtBlId(String.valueOf(wmsPreparationPlan.getPpId()));//备料id
        wmsOutboundTask.setOtWhName(wmsPreparationPlan.getPpWhName());
        wmsOutboundTask.setOtWhCode(wmsPreparationPlan.getPpWhCode());//仓库code
        wmsOutboundTask.setIsDeleted(DeleteFlagEnum.NORMAL.getValue());//逻辑未删除
        wmsOutboundTask.setGmtCreate(new Date());//创建时间
        wmsOutboundTask.setGmtModify(new Date());
        return wmsOutboundTask;
    }
}
